package com.example.mybluetooth.adapter;

import android.app.AlertDialog;
import android.bluetooth.le.ScanRecord;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Build;
import android.os.ParcelUuid;
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.recyclerview.widget.RecyclerView;

import com.example.mybluetooth.BleClientPageActivity;
import com.example.mybluetooth.BleScanHelper;
import com.example.mybluetooth.BluetoothUtils;
import com.example.mybluetooth.R;
import com.example.mybluetooth.bean.ADStructure;
import com.example.mybluetooth.bean.BleDevice;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 扫描RecyclerView的适配器,用于以列表方式展示扫描到的蓝牙设备信息
 *
 * @author mcj
 * @date 2020/3/5
 */
public class BleScanAdapter extends RecyclerView.Adapter {
    private Context context;


    public BleScanAdapter(Context context) {
        this.context = context;
//        设备列表直接使用BleScanHelper类中的静态成员变量
        Log.d("BleScanAdapter构造方法被执行","mBleDeviceList的长度为："+BleScanHelper.mBleDeviceList.size());
    }

    @NonNull
    @Override
    public BleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.blescan_list_item, parent, false);
        return new BleViewHolder(view);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        //绑定蓝牙数据，需要转换视图类型，否则用不了自定义子类的方法
        BleViewHolder bleViewHolder = (BleViewHolder) holder;
        try {
            BleDevice bleDevice = BleScanHelper.mBleDeviceList.get(position);
            System.out.println("监测下当前设备信息：");
            System.out.println(bleDevice);
            bleViewHolder.bindBleData(BleScanHelper.mBleDeviceList.get(position));
        } catch (Exception e) {
            System.out.println("绑定蓝牙数据时出错了："+e.getMessage());
            e.printStackTrace();
        }
    }

    @Override
    public int getItemCount() {
        return BleScanHelper.mBleDeviceList.size();
    }


    /**
     * BleViewHolder 内部类，用于在RecyclerView中以列表方式显示蓝牙设备基本信息
     */

    class BleViewHolder extends RecyclerView.ViewHolder {

        private Context mContext;

        //    mac地址信息
        private TextView macAddress;
        private TextView name;
        private TextView rssi;
        private TextView bondState;
        private TextView rawBtn;
        private Button connecBtn;
        private LinearLayout otherLayout;
        private ImageView bleImg;
        private LinearLayout uuid16Layout;
        private TextView uuid16Text;
        private LinearLayout uuid32Layout;
        private TextView uuid32Text;
        private LinearLayout manufacturerDataLayout;
        private TextView manufacturerDataText;
        private LinearLayout serviceDataLayout;
        private TextView serviceDataText;

        //存储广播数据单元数组，这个变量必须被初始化，否则报空指针
        private ArrayList<ADStructure> mADStructureArray  = new ArrayList<>();

        //在构造函数中初始化成员变量
        BleViewHolder(@NonNull View itemView) {
            super(itemView);
            mContext = itemView.getContext();
            macAddress = itemView.findViewById(R.id.macAddressText);
            name = itemView.findViewById(R.id.nameText);
            rssi = itemView.findViewById(R.id.rssiText);
            bondState = itemView.findViewById(R.id.bondStateText);
//          虽然在layout定义文档中，该对象为TextView，文本视图也有onClick()事件，
            rawBtn = itemView.findViewById(R.id.rawDataBtn);
            connecBtn = itemView.findViewById(R.id.connecBtn);
            otherLayout = itemView.findViewById(R.id.otherLayout);
            bleImg = itemView.findViewById(R.id.bleImg);
            uuid16Layout = itemView.findViewById(R.id.uuid16Layout);
            uuid16Text = itemView.findViewById(R.id.uuid16Text);
            uuid32Layout = itemView.findViewById(R.id.uuid32Layout);
            uuid32Text = itemView.findViewById(R.id.uuid32Text);
            manufacturerDataLayout = itemView.findViewById(R.id.manufacturerDataLayout);
            manufacturerDataText = itemView.findViewById(R.id.manufacturerDataText);
            serviceDataLayout = itemView.findViewById(R.id.serviceDataLayout);
            serviceDataText = itemView.findViewById(R.id.serviceDataText);
        }

        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        void bindBleData(BleDevice bleDevice) {
            // 设置mac地址
            macAddress.setText(bleDevice.device.getAddress());
            //设置设备名称
            String deviceName = bleDevice.device.getName();
//            以下必须增加条件判断，否则报空指针
            name.setText(deviceName==null ? "N/A" : deviceName);
            //设置信号值
            rssi.setText(bleDevice.rssi.toString());
            //绑定状态
            /**
             * Indicates the remote device is not bonded (paired).
             * <p>There is no shared link key with the remote device, so communication
             * (if it is allowed at all) will be unauthenticated and unencrypted.
                public static final int BOND_NONE = 10;
             * Indicates bonding (pairing) is in progress with the remote device.
                public static final int BOND_BONDING = 11;
             * Indicates the remote device is bonded (paired).
             * <p>A shared link keys exists locally for the remote device, so
             * communication can be authenticated and encrypted.
             * <p><i>Being bonded (paired) with a remote device does not necessarily
             * mean the device is currently connected. It just means that the pending
             * procedure was completed at some earlier time, and the link key is still
             * stored locally, ready to use on the next connection.
             * </i>
            public static final int BOND_BONDED = 12;
             */

            if (bleDevice.device.getBondState() == 12) {
                bondState.setText("已配对");
            } else {
                bondState.setText("没配对");
            }
            //判断是否可以连接
            if (!bleDevice.isConnectable) {
                connecBtn.setVisibility(View.INVISIBLE);
            } else {
                connecBtn.setVisibility(View.VISIBLE);
            }
            //判断厂商类型
            if (bleDevice.scanRecord != null) {
                //判断是否是苹果、微软的厂商id，设置他们专属标识
                if (bleDevice.scanRecord.getManufacturerSpecificData(0x4C) != null) {
                    bleImg.setImageResource(R.drawable.apple);
                } else {
                    if (bleDevice.scanRecord.getManufacturerSpecificData(0x06) != null) {
                        bleImg.setImageResource(R.drawable.windows);
                    } else
                        bleImg.setImageResource(R.drawable.bluetoothon);
                }
            } else
                bleImg.setImageResource(R.drawable.bluetoothon);

            //解析蓝牙广播数据报文
            String rawData = parseBleADData(bleDevice.scanRecordBytes);
            //初始化其他隐藏布局
            initOtherLayout(bleDevice);
            //设置监听
            String deviceName1 = bleDevice.device.getName();
            initListener(bleDevice.device.getAddress(), rawData, deviceName1 != null ? deviceName1 : "N/A");
        }

        /**
         * 初始化隐藏布局
         */
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        private void initOtherLayout(BleDevice bleDevice) {
            //先隐藏，并移除之前的布局

            otherLayout.setVisibility(View.GONE);
            if (bleDevice.scanRecord != null) {
                ScanRecord scanRecord = bleDevice.scanRecord;
                uuid16Layout.setVisibility(View.GONE);
                uuid32Layout.setVisibility(View.GONE);
                List<ParcelUuid> serviceUuids = scanRecord.getServiceUuids();
                if (serviceUuids != null) {
                    for (ADStructure adStructure : mADStructureArray) {
                        switch (adStructure.type) {
                            //完整的16bit UUID 列表
                            case "0x03": {
                                uuid16Text.setText("");
                                //除去之前添加的0x
                                final String dataStr = adStructure.data.substring(2, adStructure.data.length());
                                for (int i = 0; i < dataStr.length() / 4; i++) {
                                    final String uuid = "0x" + dataStr.substring(2 + i * 4, 4 + i * 4) + dataStr.substring( i * 4, 2 + i * 4);
                                    if (uuid16Text.getText().equals("")) {
                                        uuid16Text.setText(uuid);
                                    } else {
                                        uuid16Text.setText(uuid16Text.getText() + "," + uuid);
                                    }

                                }
                                uuid16Text.setVisibility(View.VISIBLE);
                                break;
                            }
                            //完整的32bit UUID 列表
                            case "0x05": {
                                uuid32Text.setText("");
                                //除去之前添加的0x
                                final String dataStr = adStructure.data.substring(2, adStructure.data.length());
                                for (int i = 0; i < dataStr.length() / 8; i++) {
                                    final String uuid = "0x" + dataStr.substring(6 + i * 8, 8 + i * 8) + dataStr.substring(4 + i * 8, 6 + i * 8) +
                                            dataStr.substring(2 + i * 8, 4 + i * 8) + dataStr.substring( i * 8, 2 + i * 8);
                                    if (uuid32Text.getText().equals("")) {
                                        uuid32Text.setText(uuid);
                                    } else {
                                        uuid32Text.setText(uuid32Text.getText() + "," + uuid);
                                    }
                                }
                                uuid32Text.setVisibility(View.VISIBLE);
                                break;
                            }
                        }
                    }
                }
                //隐藏
                manufacturerDataLayout.setVisibility(View.GONE);
                //厂商数据
                SparseArray<byte[]> manufacturerSpecificData = scanRecord.getManufacturerSpecificData();
                if (manufacturerSpecificData != null) {
                    //添加厂商数据信息
                    for (ADStructure adStructure : mADStructureArray
                    ) {
                        if (adStructure.type.equals("0xFF")) {
                            //除去之前添加的0x
                            final String data = (String) adStructure.data.subSequence(2, adStructure.data.length());
                            //获取厂商id
                            final String manufacturerId = data.substring(2, 4) + data.substring(0, 2);
                            //获取真正的厂商数据
                            final String manufacturerData = data.substring(4, data.length());
                            manufacturerDataText.setText("厂商ID: 0x" + manufacturerId + "\n数据:0x" + manufacturerData);
                            manufacturerDataLayout.setVisibility(View.VISIBLE);
                            break;

                        }

                    }
                }
                //隐藏服务数据布局
                serviceDataLayout.setVisibility(View.GONE);
                //服务数据
                Map<ParcelUuid, byte[]> serviceData = scanRecord.getServiceData();
                if (serviceData != null) {
                    serviceDataText.setText("");
                    //添加厂商数据信息
                    for (ADStructure adStructure : mADStructureArray
                    ) {
                        switch (adStructure.type) {
                            //16-bit 服务数据
                            case "0x16": {
                                //除去之前添加的0x
                                final String data = (String) adStructure.data.subSequence(2, adStructure.data.length());
                                //获取16bit的uuid
                                final String uuid = "0x" + data.substring(2, 4) + data.substring(0, 2);
                                //获取对应的数据
                                final String serviceData1 = data.substring(4, data.length());
                                serviceDataText.setText("16-bit UUID: 0x" + uuid + "\n数据: 0x" + serviceData);
                                serviceDataLayout.setVisibility(View.VISIBLE);
                                break;
                            }
//                    android不会发出32位的数据服务
                            case "0x20":
//                        什么也不做
                        }

                    }
                }
            }
            //设置厂商数据
        }


        /**
         * 设置点击监听
         */
        private void initListener(String address, String rawData, String name) {
            //连接按钮点击监听
            connecBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mContext.startActivity(BleClientPageActivity.newIntent(mContext, address, name));
                }
            });
//        原始数据按钮点击监听
            rawBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    showDialog(rawData);
                }
            });
            //列表item点击监听
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (otherLayout.getVisibility() == View.GONE) {
                        otherLayout.setVisibility(View.VISIBLE);
                    } else {
                        otherLayout.setVisibility(View.GONE);
                    }
                }
            });

        }

        /**
         * 统计数据单元，展示dialog
         */
        private void showDialog(String rawDataStr) {
//注意这个this.itemView是recyclerView的公有成员变量，
            final View view = LayoutInflater.from(itemView.getContext()).inflate(R.layout.blescan_dialog, null);
            final TableLayout mTableLayout = view.findViewById(R.id.mTableLayout);
            final TextView rawData = view.findViewById(R.id.rawDataText);
            final TextView positiveBtn = view.findViewById(R.id.positiveBtn);
            //显示原始数据
            rawData.setText("0x" + rawDataStr.toUpperCase());
            //设置数据单元
            for (ADStructure adStructure : mADStructureArray) {
                setBleADStructureTable(adStructure.length, adStructure.type, adStructure.data, mTableLayout);
            }
            //展示dialog
            AlertDialog dialog = new AlertDialog.Builder(mContext).setView(view).show();

//设置点击事件
            positiveBtn.setOnClickListener(new View.OnClickListener() {
                @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
                @Override
                public void onClick(View v) {
                    dialog.dismiss();
                }
            });

            //原始数据点击事件
            rawData.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
                    final ClipData clip = ClipData.newPlainText("mcj", rawData.getText());
                    clipboard.setPrimaryClip(clip);
                    Toast.makeText(mContext, "复制成功", Toast.LENGTH_SHORT).show();
                }
            });
            //列表item点击监听
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (otherLayout.getVisibility() == View.GONE) {
                        otherLayout.setVisibility(View.VISIBLE);
                    } else {
                        otherLayout.setVisibility(View.GONE);
                    }
                }
            });

        }

        /**
         * 解析蓝牙广播报文，获取数据单元
         */
        private String parseBleADData(byte[] scanRecordBytes) {
            //将字节数组转十六进制字符串
            String rawDataStr = BluetoothUtils.bytesToHexString(scanRecordBytes);
            //清空之前解析的数据单元
            System.out.println("mADStructureArray的值是："+mADStructureArray);
            this.mADStructureArray.clear();
            //存储实际数据段
            String dataStr = "";

            while (true) {
                //取长度
                String lengthStr = rawDataStr != null ? rawDataStr.substring(0, 2) : null;
                //如果长度为0，则退出
                if (lengthStr.equals("00")) {
                    break;
                }
                //将长度转10进制
                int length = Integer.parseInt(lengthStr, 16);
                //length表示后面多少字节也属于该数据单元，所以整个数据单元的长度 = length + 1
                String data = rawDataStr.substring(0, (length + 1) * 2);
                //存储每个数据单元的值
                dataStr += data;
                //裁剪原始数据，方便后面裁剪数据单元
                rawDataStr = rawDataStr.substring((length + 1) * 2, rawDataStr.length());
                //创建广播数据单元bean，并存储到数据中
                //第一个字节是长度，第二个字节是类型，再后面才是数据（一个字节用两个十六进制字符串表示）
                mADStructureArray.add(new ADStructure(length, "0x" + data.substring(2, 4).toUpperCase(),
                        "0x" + data.substring(4, data.length()).toUpperCase()));

            }
            //返回蓝牙广播数据报文
            return dataStr;
        }

        /**
         * 设置广播数据单元
         */
        private void setBleADStructureTable(int length, String type, String data, TableLayout parent) {
            //创建表格
            TableRow tableRow = new TableRow(mContext);
            //创建length视图
            TextView lengthView = new TextView(mContext);
            lengthView.setLayoutParams(new TableRow.LayoutParams(1, ViewGroup.LayoutParams.WRAP_CONTENT));
            int padding = (int) dp2px(4.0F);
            lengthView.setPadding(padding, padding, padding, padding);
            lengthView.setText(String.valueOf(length));
            lengthView.setGravity(Gravity.CENTER);
            tableRow.addView(lengthView);
            //创建Type视图
            TextView typeView = new TextView(mContext);
            typeView.setLayoutParams(new TableRow.LayoutParams(1, ViewGroup.LayoutParams.WRAP_CONTENT));
            typeView.setPadding(padding, padding, padding, padding);
            typeView.setText(type);
            typeView.setGravity(Gravity.CENTER);
            tableRow.addView(typeView);
            //创建Value视图
            TextView valueView = new TextView(mContext);
            TableRow.LayoutParams valueLayoutParams = new TableRow.LayoutParams(1, ViewGroup.LayoutParams.WRAP_CONTENT);
            valueLayoutParams.span = 3;
            valueView.setLayoutParams(valueLayoutParams);
            valueView.setPadding(padding, padding, padding, padding);
            valueView.setText(data);
            valueView.setGravity(Gravity.CENTER);
            tableRow.addView(valueView);
            parent.addView(tableRow);
        }

        private float dp2px(float num) {
            return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, num, itemView.getContext().getResources().getDisplayMetrics());
        }
    }
}
